// server是服务器，service是服务
#ifndef CHATSERVICE_H
#define CHATSERVICE_H

#include "json.hpp"
#include "usermodel.hpp"
#include "offlinemessagemodel.hpp"
#include "friendmodel.hpp"
#include "groupmodel.hpp"
#include "redis.hpp"

#include <muduo/net/TcpConnection.h>
#include <unordered_map>
#include <functional>
#include <memory>
#include <mutex>
using namespace std;
using namespace muduo;
using namespace muduo::net;

using json = nlohmann::json;
// 处理消息的事件回调方法类型
using MsgHander = std::function<void(const TcpConnectionPtr& conn, json &js, Timestamp time)>;

/**
 * 聊天服务器业务类
 * 主要封装和业务相关的代码，对象本身有一个实例就够了，所以设计为单例模式
 * 给 msgid 映射事件回调
 */
class ChatService
{
public:
    // 获取单例对象的接口函数
    static ChatService* getInstance();
    // 处理登录业务
    void login(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 处理注册业务
    void reg(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 一对一聊天业务
    void oneChat(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 添加好友业务
    void addFriend(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 创建群组业务
    void createGroup(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 加入群组业务
    void addGroup(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 群组聊天业务
    void groupChat(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 处理注销业务
    void logout(const TcpConnectionPtr &conn, json &js, Timestamp time);
    // 获取消息对应的处理器
    MsgHander getHander(int msgid);
    // 处理客户端异常退出
    void clientCloseException(const TcpConnectionPtr &conn);
    // 服务器异常，业务重置方法
    void reset();
    // 从 redis 消息队列中获取订阅的消息
    void handleRedisSubscribeMessage(int userid, std::string msg);

private:
    ChatService();

    // 数据操作类对象
    UserModel _userModel;
    OfflineMsgModel _offlineMsgModel;
    FriendModel _friendModel;
    GroupModel _groupModel;

    // redis 操作对象
    Redis _redis;

    // 消息处理器表 存储消息id-对应消息处理业务方法
    unordered_map<int, MsgHander> _msgHandlerMap;
    // 存储登录成功的用户的TcpConnectionPtr，id -- 用户id
    unordered_map<int, TcpConnectionPtr> _userConnMap;

    // 互斥锁，保证 _userConnMap 的线程安全，onMessage 会在多线程中回调
    std::mutex _connMutex;
};

#endif